package com.cf.redis.service.impl;

import com.cf.redis.dao.SysCodeDao;
import com.cf.redis.entity.SysCodeEntity;
import com.cf.redis.entity.UserEntity;
import com.cf.redis.service.SysCodeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author: YangF
 * @Date: 2021-01-21 15:21
 * @description:
 */
@Service("sysCodeService")
public class SysCodeServiceImpl implements SysCodeService {

    private Logger logger = LoggerFactory.getLogger(SysCodeService.class);

    @Autowired
    private SysCodeDao sysCodeDao;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 查询所有数字字典
     * @return
     */
    @Override
    public List<SysCodeEntity> queryCodeAll() {
        logger.info("先从缓存中查找，如果没有则去数据进行查询");
        List<SysCodeEntity> codeList = (List<SysCodeEntity>)redisTemplate.opsForList().leftPop("codeList");
        if (codeList == null) {
            logger.info("说明缓存中没有数据，则到数据库中查询");
            codeList = sysCodeDao.queryCodeAll();
            logger.info("将数据库获取的数据存入缓存");
            redisTemplate.opsForList().leftPush("codeList", codeList);
        } else {
            logger.info("则说明缓存中存在，直接从缓存中获取数据");
        }
        return codeList;
    }

    /**
     * 解决高并发下 缓存穿透问题
     * 方法1：加 synchronized 效率低
     * */
    public synchronized SysCodeEntity getSysCodeById(Integer id){
//        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //查询缓存
        SysCodeEntity sysCodeEntity = (SysCodeEntity)redisTemplate.opsForValue().get("syslist");
        //判断缓存是否为空
        if (null == sysCodeEntity){
            logger.info("说明缓存中没有数据，则到数据库中查询");
//            sysCodeEntity = sysCodeDao.selectByPrimaryKey(id);
            //放入缓存
            logger.info("将数据库获取的数据存入缓存");
            redisTemplate.opsForValue().set("syslist",sysCodeEntity);
        }else {
            logger.info("则说明缓存中存在，直接从缓存中获取数据");
        }
        return sysCodeEntity;
    }

    /**
     * 解决高并发下 缓存穿透问题
     * 方法2：双重检测机制 加 synchronized 效率低
     * */
    public SysCodeEntity getSysCodeById2(Integer id){
        SysCodeEntity sysCodeEntity = (SysCodeEntity)redisTemplate.opsForValue().get("syslist2");
        if (null == sysCodeEntity){
            //双重检测锁实现
            synchronized (this){
               sysCodeEntity = (SysCodeEntity)redisTemplate.opsForValue().get("syslist2");
               if (null == sysCodeEntity){
//                   sysCodeEntity = sysCodeEntity = sysCodeDao.selectByPrimaryKey(id);
                   redisTemplate.opsForValue().set("syslist2",sysCodeEntity);
               }
            }
        }
        return sysCodeEntity;
    }
}
